package com.aliyun.messagemgt.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.messagemgt.common.dto.send.MsgMiddleResult;
import com.aliyun.messagemgt.common.dto.send.MsgRecordVO;
import com.aliyun.messagemgt.common.dto.send.PushChannelInfo;
import com.aliyun.messagemgt.common.dto.send.Receiver;
import com.aliyun.messagemgt.common.enums.ChannelTypeEnum;
import com.aliyun.messagemgt.common.enums.PushResultEnum;
import com.aliyun.messagemgt.sendplugin.SendStrategy;
import com.aliyun.messagemgt.sendplugin.SendStrategyFactory;
import com.aliyun.messagemgt.util.AlibabaHttpUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @ClassName: LanXinSendStrategy
 * @Description:
 * @Author: wugongzi
 * @Date: 2022/4/12 11:22
 * @Version: 1.0
 */
@Service
public class LanXinSendStrategy implements SendStrategy, InitializingBean {


    private static final Logger logger = LoggerFactory.getLogger(LanXinSendStrategy.class);

    @Override
    public void afterPropertiesSet() {
        SendStrategyFactory.register(ChannelTypeEnum.LANXIN.getType(), this);
    }

    /**
     * 查询TOKEN
     */
    private String queryToken(String address, String appId, String secret, String grandType) {
        logger.info("queryToken begin");
        String url = String.format("%s%s?appid=%s&secret=%s&grant_type=%s", address, LanXinConstant.TOKEN_API, appId, secret, grandType);
        logger.info("queryToken url={}", url);

        String returnMsg = AlibabaHttpUtil.httpRequest(url, HttpMethod.POST.name(), null);
        if (StringUtils.isEmpty(returnMsg)) {
            logger.error("queryToken returnMsg is null");
            return null;
        }

        LanXinQryTokenResult tokenResult = JSONObject.parseObject(returnMsg, LanXinQryTokenResult.class);
        if (null == tokenResult) {
            logger.error("queryToken tokenResult is null");
            return null;
        }
        if (!tokenResult.isSuccess()) {
            logger.error("queryToken failure, errcode!=0, errcode={}", tokenResult.getErrCode());
            return null;
        }
        if (StringUtils.isEmpty(tokenResult.getAccessToken())) {
            logger.error("queryToken failure, access_token is null");
            return null;
        }
        logger.info("queryToken end, access_token={}", tokenResult.getAccessToken());
        return tokenResult.getAccessToken();
    }

    /**
     * 查询员工手机号
     */
    private String queryEmployeeMobile(String address, String accessToken, String employeeCode) {
        logger.info("queryEmployeeMobile begin");
        String url = String.format("%s%s?access_token=%s&serialNumber=%s", address, LanXinConstant.GET_USER_INFO_API, accessToken, employeeCode);
        logger.info("queryEmployeeMobile url={}", url);

        String returnMsg = AlibabaHttpUtil.httpRequest(url, HttpMethod.POST.name(), null);
        if (StringUtils.isEmpty(returnMsg)) {
            logger.error("queryEmployeeMobile returnMsg is null");
            return null;
        }

        LanXinQryUserResult userResult = JSONObject.parseObject(returnMsg, LanXinQryUserResult.class);
        if (null == userResult) {
            logger.error("queryEmployeeMobile userResult is null");
            return null;
        }
        if (!userResult.isSuccess()) {
            logger.error("queryEmployeeMobile failure, errcode!=0, errcode={}", userResult.getErrCode());
            return null;
        }
        if (null == userResult.getOrgMember() || StringUtils.isEmpty(userResult.getOrgMember().getMobile())) {
            logger.error("queryEmployeeMobile failure, orgMember is null or mobile is null");
            return null;
        }
        logger.info("queryEmployeeMobile end, mobile={}", userResult.getOrgMember().getMobile());
        return userResult.getOrgMember().getMobile();
    }

    /**
     * 群发消息
     */
    private boolean massSend2Lanxin(String address, String accessToken, LanXinMassSendParam lanXinMassSendParam) {
        logger.info("massSend2Lanxin begin");
        String url = String.format("%s%s?access_token=%s", address, LanXinConstant.SEND_MASS_MSG_API, accessToken);
        logger.info("massSend2Lanxin url={}", url);

        String paramJSON = JSON.toJSONString(lanXinMassSendParam);
        logger.info("massSend2Lanxin paramJSON={}", paramJSON);

        String returnMsg = AlibabaHttpUtil.httpRequest(url, HttpMethod.POST.name(), paramJSON);
        if (StringUtils.isEmpty(returnMsg)) {
            logger.error("massSend2Lanxin returnMsg is null");
            return false;
        }

        LanXinCommResult sendResult = JSONObject.parseObject(returnMsg, LanXinCommResult.class);
        if (null == sendResult) {
            logger.error("massSend2Lanxin sendResult is null");
            return false;
        }
        if (!sendResult.isSuccess()) {
            logger.error("massSend2Lanxin failure, errcode!=0, errcode={}", sendResult.getErrCode());
            return false;
        }
        logger.info("massSend2Lanxin end, errcode={}, errmsg={}", sendResult.getErrCode(), sendResult.getErrMsg());
        return true;
    }

    private void wrapSendFailedResult(List<MsgMiddleResult> results, String description, List<Receiver> receivers) {
        String errMsg = String.format("%s, %s", PushResultEnum.LANXIN_PUSH_ERROR.getDescription(), description);
        MsgMiddleResult msgMiddleResult = new MsgMiddleResult().setPushResultCode(PushResultEnum.LANXIN_PUSH_ERROR.getErrorCode())
                .setPushResultDescription(errMsg).setReceivers(receivers);
        results.add(msgMiddleResult);
    }

    @Override
    public void sendMessage(PushChannelInfo pushChannelInfo, MsgRecordVO msgRecordVO) {
        //1、检查参数合法性
        if (null == pushChannelInfo || null == msgRecordVO) {
            logger.error("sendMessage pushChannelInfo or msgRecordVO is null");
            return;
        }
        if (StringUtils.isEmpty(pushChannelInfo.getApiUrl()) ||
                StringUtils.isEmpty(pushChannelInfo.getApiAppKey()) ||
                StringUtils.isEmpty(pushChannelInfo.getApiAppSecret()) ||
                StringUtils.isEmpty(pushChannelInfo.getGrandType())) {
            logger.error("sendMessage apiUrl、appId、secret、grandType is null");
            return;
        }
        if (CollectionUtils.isEmpty(msgRecordVO.getReceivers())) {
            logger.error("sendMessage msgRecordVO.getReceivers() is empty");
            return;
        }
        if (CollectionUtils.isEmpty(msgRecordVO.getContents()) ||
                null == msgRecordVO.getContents().get(0) ||
                StringUtils.isEmpty(msgRecordVO.getContents().get(0).getContent())) {
            logger.error("sendMessage msgRecordVO.getContents() is empty");
            return;
        }

        //2、工号去重
        Set<String> employeeCodeSet = new HashSet<>();
        for (Receiver receiver : msgRecordVO.getReceivers()) {
            String employeeCode = receiver.getEmployeeCode();
            if (StringUtils.isBlank(employeeCode)) {
                continue;
            }
            employeeCodeSet.add(employeeCode);
        }
        if (employeeCodeSet.isEmpty()) {
            logger.error("sendMessage employeeSet is empty");
            return;
        }

        //3、准备变量
        List<MsgMiddleResult> results = msgRecordVO.getResults();
        String systemName = pushChannelInfo.getApiName();
        String apiUrl = pushChannelInfo.getApiUrl();
        String grandType = pushChannelInfo.getGrandType();
        String appId = pushChannelInfo.getApiAppKey();
        String secret = pushChannelInfo.getApiAppSecret();
        logger.info("LANXIN端push基本参数为：systemName：{}, apiUrl:{}, grandType:{}, appid:{}, secret:{}, employeeCodes:{}",
                systemName, apiUrl, grandType, appId, secret, JSON.toJSON(employeeCodeSet));

        //4、获取token
        String token = queryToken(apiUrl, appId, secret, grandType);
        if (StringUtils.isEmpty(token)) {
            String errMsg = "queryToken failed";
            logger.error("sendMessage {}", errMsg);
            wrapSendFailedResult(results, errMsg, msgRecordVO.getReceivers());
            return;
        }

        //5、查询员工手机号
        List<String> mobileList = new ArrayList<>();
        for (String employeeCode : employeeCodeSet) {
            String tmpMobile = queryEmployeeMobile(apiUrl, token, employeeCode);
            if (StringUtils.isEmpty(tmpMobile)) {
                logger.error("sendMessage queryEmployeeMobile failed, employee:{}", employeeCode);
                continue;
            }
            logger.info("sendMessage queryEmployeeMobile success, employee:{} , mobile:{}", employeeCode, tmpMobile);
            mobileList.add(tmpMobile);
        }
        if (CollectionUtils.isEmpty(mobileList)) {
            String errMsg = "mobileList is empty";
            logger.error("sendMessage {}", errMsg);
            wrapSendFailedResult(results, errMsg, msgRecordVO.getReceivers());
            return;
        }

        //6、发送消息
        LanXinMassSendParam lanXinMassSendParam = new LanXinMassSendParam();
        lanXinMassSendParam.setToAll(false);
        lanXinMassSendParam.setToUsers(mobileList);
        lanXinMassSendParam.setMsgType(LanXinConstant.MSG_TYPE_TEXT);
        LanXinMassSendParamText text = new LanXinMassSendParamText();
        text.setContent(msgRecordVO.getContents().get(0).getContent());
        lanXinMassSendParam.setText(text);
        boolean isSuccess = massSend2Lanxin(apiUrl, token, lanXinMassSendParam);
        if (!isSuccess) {
            String errMsg = "massSend2Lanxin failed";
            logger.error("sendMessage {}", errMsg);
            wrapSendFailedResult(results, errMsg, msgRecordVO.getReceivers());
            return;
        }
        MsgMiddleResult msgMiddleResult = new MsgMiddleResult().setPushResultCode(PushResultEnum.PUSH_SUCCESS.getErrorCode())
                .setPushResultDescription(PushResultEnum.PUSH_SUCCESS.getDescription()).setReceivers(msgRecordVO.getReceivers());
        results.add(msgMiddleResult);
        logger.info("sendMessage massSend2Lanxin successfully");
    }
}
